#pragma once

#include <cassert>
#include <cstddef>
#include <vector>
#include <cstring>
#include <iostream>

#define LIKELY(x) __builtin_expect(!!(x), 1)   // 告诉编译器 x 更可能为 true，优化分支预测
#define UNLIKELY(x) __builtin_expect(!!(x), 0) // 告诉编译器 x 更可能为 false

// 断言：当 cond 为 false 时打印错误信息并终止程序。
// 使用 `noexcept` 表示这个函数承诺不会抛出异常。
inline auto ASSERT(bool cond, const std::string &msg) noexcept {
  if (UNLIKELY(!cond)) { // 如果不满足条件，走“少见”分支，提高常见路径性能
    std::cerr << "ASSERT : " << msg << "\n";

    exit(EXIT_FAILURE); // 立即退出程序，返回失败状态
  }
}

// 致命错误处理：无条件打印错误信息并终止程序。
// 一般用于遇到不可恢复的严重错误。
inline auto FATAL(const std::string &msg) noexcept {
  std::cerr << "FATAL : " << msg << "\n";

  exit(EXIT_FAILURE); // 终止程序，返回失败状态
}

namespace Legacy {

/**
 * @brief 原始版本的固定容量内存池实现。
 *
 * 模板参数 @p T 表示存储的对象类型。构造函数会在内部 vector 中预先放入
 * `num_elems` 个 ObjectBlock，每个块都包含一个 T 对象和空闲标记。
 */
template <typename T>
class MemPool final {
public:
  explicit MemPool(std::size_t num_elems)
      : store_(num_elems, {T(), true}) {
    ASSERT(reinterpret_cast<const ObjectBlock*>(&(store_[0].object_)) ==
               &(store_[0]),
           "T 必须是 ObjectBlock 的首个成员。");
  }

  /**
   * @brief 在当前 next_free_index_ 指向的槽位上构造一个 T 对象。
   * @note 参数按值传递，可能会产生一次复制。
   */
  template <typename... Args>
  T* allocate(Args... args) noexcept {
    auto obj_block = &(store_[next_free_index_]);
    ASSERT(obj_block->is_free_,
           "索引 " + std::to_string(next_free_index_) + " 的块应为空闲。");
    T* ret = &(obj_block->object_);
    ret     = new (ret) T(args...); // placement new
    obj_block->is_free_ = false;

    updateNextFreeIndex();
    return ret;
  }

  /**
   * @brief 回收对象：仅修改空闲标记，不调用析构函数。
   * @warning 对拥有资源的类型存在风险。
   */
  void deallocate(const T* elem) noexcept {
    const auto elem_index =
        (reinterpret_cast<const ObjectBlock*>(elem) - &store_[0]);
    ASSERT(elem_index >= 0 && static_cast<std::size_t>(elem_index) < store_.size(),
           "被回收的对象不属于该内存池。");
    ASSERT(!store_[elem_index].is_free_,
           "索引 " + std::to_string(elem_index) + " 应为在用状态。");
    store_[elem_index].is_free_ = true;
  }

  MemPool() = delete;
  MemPool(const MemPool&) = delete;
  MemPool(const MemPool&&) = delete;
  MemPool& operator=(const MemPool&) = delete;
  MemPool& operator=(const MemPool&&) = delete;

private:
  /**
   * @brief 查找下一个空闲块；若无空闲块，将触发断言。
   */
  void updateNextFreeIndex() noexcept {
    const auto initial_free_index = next_free_index_;
    while (!store_[next_free_index_].is_free_) {
      ++next_free_index_;
      if (UNLIKELY(next_free_index_ == store_.size())) {
        next_free_index_ = 0;
      }
      if (UNLIKELY(initial_free_index == next_free_index_)) {
        ASSERT(false, "内存池空间已耗尽。");
      }
    }
  }

  struct ObjectBlock {
    T object_;
    bool is_free_ = true;
  };

  std::vector<ObjectBlock> store_;
  std::size_t next_free_index_ = 0;
};

} // namespace Legacy